package com.zzq.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.zzq.domain.dto.SmilePointGoodsDTO;
import com.zzq.domain.entity.SmileBlindboxGoods;
import com.zzq.domain.entity.SmileBlindboxPrizeRecord;
import com.zzq.domain.entity.SmileCoupon;
import com.zzq.enumerate.GoodsTypeEnum;
import com.zzq.exception.NormalException;
import com.zzq.result.SmileResult;
import com.zzq.security.util.UserUtil;
import com.zzq.service.*;
import com.zzq.subservice.EarnPointsSubService;
import com.zzq.util.CommonUtils;
import com.zzq.util.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.security.auth.login.LoginException;
import java.util.*;

@Service
public class ClientBlindboxServiceImpl implements ClientBlindboxService {

    @Autowired
    SmileBlindboxPrizeRecordService blindboxPrizeRecordService;

    @Autowired
    SmileBlindboxGoodsService blindboxGoodsService;

    @Autowired
    SmileCouponService couponService;

    @Autowired
    SmilePointGoodsService pointGoodsService;

    @Autowired
    SmileClientService clientService;

    @Autowired
    EarnPointsSubService earnPointsSubService;

    @Override
    @Transactional
    public SmileResult prizeDraw(String clientNo) throws LoginException {
        if (!UserUtil.getUser().getClientNo().equals(clientNo)) {
            throw new LoginException("用户信息有误");

        }

        List<SmileBlindboxGoods> prizeList = blindboxGoodsService.list();
        Long clientId = UserUtil.getUserID();
        SmileBlindboxPrizeRecord lastRecord = blindboxPrizeRecordService.getLastRecord(clientId);
        if (!ObjectUtils.isEmpty(lastRecord)) {
            if (CommonUtils.isWithinDays(lastRecord.getCreatedTime(),new Date(),7)) {
                int i = CommonUtils.remainingDays( lastRecord.getCreatedTime(),new Date(),7);
                return  SmileResult.waring("抽奖冷却时间未过",i);
            }
        }

        //抽奖
        SmileBlindboxGoods blindboxGoods = lottery(prizeList);

        //添加商品
        Long goodsId = blindboxGoods.getGoodsId();
        SmilePointGoodsDTO pointGoodsDTO = pointGoodsService.getPointGoodsDTO(goodsId);
        if (pointGoodsDTO.getGoodsType().equals(GoodsTypeEnum.COUPON.getName())) {
            Long couponRuleId = pointGoodsDTO.getCouponRuleId();
            couponService.addCoupon(clientId, clientNo, couponRuleId, null);
        }else if (pointGoodsDTO.getGoodsType().equals(GoodsTypeEnum.POINTS.getName())){
            Integer goodsPointNum = pointGoodsDTO.getGoodsPointNum();
            earnPointsSubService.prizePoints(clientId,clientNo,goodsPointNum);
        }else {
            //未来存在其他普同商品
        }


        SmileBlindboxPrizeRecord prizeRecord = new SmileBlindboxPrizeRecord();
        prizeRecord.setClientId(clientId);
        prizeRecord.setGoodsId(goodsId);
        prizeRecord.setBlindoxGoodsId(prizeRecord.getId());
        blindboxPrizeRecordService.save(prizeRecord);
        return SmileResult.sucess(blindboxGoods);
    }


    public  SmileBlindboxGoods lottery(List<SmileBlindboxGoods> prizeList) {
        //按照权重从小到大排序奖品
        prizeList.sort(Comparator.comparingInt(SmileBlindboxGoods::getGoodsWeight));

        //计算节点 节点的数量比奖品的数量多一个，即0
        List<Integer> nodeList = new ArrayList<>();
        //第一个节点为0
        nodeList.add(0);
        for (SmileBlindboxGoods prize : prizeList) {
            //每一个节点等于前一个节点+当前奖品的权重
            nodeList.add(nodeList.get(nodeList.size() - 1) + prize.getGoodsWeight());
        }

        //生成 0-结束节点 的随机数
        int randomInt = RandomUtil.randomInt(0, nodeList.get(nodeList.size() - 1));

        //最终抽奖逻辑 此处需要从第二个节点开始遍历
        for (int i = 1; i < nodeList.size(); i++) {
            //本次节点
            Integer endNode = nodeList.get(i);
            //前一个节点
            Integer startNode = nodeList.get(i - 1);
            //若随机数大于等于前一个节点并且小于本节点，在prizeList中位于i-1位置的奖品为抽中奖品
            //Tip：比较大小时，左闭右开与左开右闭都可以，不影响整体概率
            if (randomInt >= startNode
                    && randomInt < endNode) {
                return prizeList.get(i - 1);
            }
        }
        throw new NormalException("程序异常 生成的随机数不在任何奖品区间内");
    }

}
